using MediatR;
using Microsoft.Extensions.Logging;
using RBAC.Domain.Dto.Output;
using RBAC.Domain.ProcessManagement;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Read.Api.Application.Command.ProcessManagements;
using System.Text;
using System.Linq;

namespace RBAC.Read.Api.Application.Handler.ProcessManagements
{
    /// <summary>
    /// 工序列表分页（联查）处理器
    /// </summary>
    public class GetProcessesPageHandler : IRequestHandler<GetProcessesPageCommand, APIPaging<ProcessListDto>>
    {
        private readonly IBaseRepository<ProcessInfo> _repo;
        private readonly ILogger<GetProcessesPageHandler> _logger;

        public GetProcessesPageHandler(
            IBaseRepository<ProcessInfo> repo,
            ILogger<GetProcessesPageHandler> logger)
        {
            _repo = repo;
            _logger = logger;
        }

        public Task<APIPaging<ProcessListDto>> Handle(GetProcessesPageCommand request, CancellationToken cancellationToken)
        {
            var result = new APIPaging<ProcessListDto>();
            try
            {
                var (where, param) = BuildWhere(request);

                // 统计总数
                var countSql = $@"SELECT COUNT(1)
                                  FROM ProcessInfo pi
                                  LEFT JOIN ProcessClassification pc ON pi.ClassificationId = pc.Id AND pc.IsDeleted = 0
                                  LEFT JOIN Department dm ON pi.DepartmentId = dm.Id AND dm.IsDeleted = 0
                                  LEFT JOIN `User` u ON pi.OwnerUserId = u.Id AND u.IsDeleted = 0
                                  {(string.IsNullOrWhiteSpace(where) ? "" : "WHERE " + where)}";
                var total = _repo.QueryFirstOrDefault<int>(countSql, param);

                // 数据查询
                var dataSql = $@"SELECT
                                    pi.Id,
                                    pi.ProcessCode,
                                    pi.ProcessName,
                                    pi.SystemCode,
                                    pi.ClassificationId,
                                    COALESCE(pc.ClassificationName, pi.ClassificationName) AS ClassificationName,
                                    pi.DepartmentId,
                                    COALESCE(dm.DepartmentName, pi.DepartmentName) AS DepartmentName,
                                    pi.OwnerUserId,
                                    COALESCE(u.UserName, pi.OwnerUserName) AS OwnerUserName,
                                    pi.Status,
                                    pi.Remark,
                                    pi.CreateTime,
                                    pi.CreateUser
                                  FROM ProcessInfo pi
                                  LEFT JOIN ProcessClassification pc ON pi.ClassificationId = pc.Id AND pc.IsDeleted = 0
                                  LEFT JOIN Department dm ON pi.DepartmentId = dm.Id AND dm.IsDeleted = 0
                                  LEFT JOIN `User` u ON pi.OwnerUserId = u.Id AND u.IsDeleted = 0
                                  {(string.IsNullOrWhiteSpace(where) ? "" : "WHERE " + where)}
                                  ORDER BY {request.OrderBy}
                                  LIMIT @Offset, @PageSize";

                param["Offset"] = (request.PageIndex - 1) * request.PageSize;
                param["PageSize"] = request.PageSize;

                var rows = _repo.Query<ProcessListDto>(dataSql, param) ?? new List<ProcessListDto>();

                // 附件查询：为当前页的工序批量查询附件并回填
                if (rows.Count > 0)
                {
                    var ids = rows.Select(r => r.Id).ToList();
                    var attSql = @"SELECT ProcessId, FileName, FileUrl, FileSize, ContentType, Status, Remark
                                   FROM ProcessAttachment
                                   WHERE IsDeleted = 0 AND ProcessId IN @Ids";
                    var atts = _repo.Query<ProcessAttachmentDto>(attSql, new { Ids = ids }) ?? new List<ProcessAttachmentDto>();
                    var lookup = atts.GroupBy(a => a.ProcessId).ToDictionary(g => g.Key, g => g.ToList());
                    foreach (var r in rows)
                    {
                        if (lookup.TryGetValue(r.Id, out var list))
                            r.Attachments = list;
                        else
                            r.Attachments = new List<ProcessAttachmentDto>();
                    }
                }

                result.Code = APIEnums.Success;
                result.PageDatas = rows;
                result.TotalCount = total;
                result.Msg = "获取工序列表成功";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取工序列表失败: {Message}", ex.Message);
                result.Code = APIEnums.Error;
                result.Msg = "获取工序列表失败";
                result.PageDatas = new List<ProcessListDto>();
                result.TotalCount = 0;
            }

            return Task.FromResult(result);
        }

        private (string where, Dictionary<string, object> param) BuildWhere(GetProcessesPageCommand req)
        {
            var conds = new List<string> { "pi.IsDeleted = 0" };
            var p = new Dictionary<string, object>();

            if (!string.IsNullOrWhiteSpace(req.Keyword))
            {
                conds.Add("(pi.ProcessCode LIKE @kw OR pi.ProcessName LIKE @kw)");
                p["kw"] = $"%{req.Keyword}%";
            }
            if (req.ClassificationId.HasValue)
            {
                conds.Add("pi.ClassificationId = @ClassificationId");
                p["ClassificationId"] = req.ClassificationId.Value;
            }
            if (req.DepartmentId.HasValue)
            {
                conds.Add("pi.DepartmentId = @DepartmentId");
                p["DepartmentId"] = req.DepartmentId.Value;
            }
            if (req.Status.HasValue)
            {
                conds.Add("pi.Status = @Status");
                p["Status"] = req.Status.Value;
            }

            var where = string.Join(" AND ", conds);
            return (where, p);
        }
    }
}
